/* Sinc based filter to emulate the output characteristcs of the Amiga's
   sound system.
   Christopher O'Neill 1/7/06
   Based on Antti S. Lankila's interpolation guide (http://bel.fi/~alankila/modguide/interpolate.txt)
 */

/* Paula's clock = 3546895Hz (PAL) */
#ifndef AMIGAFILTER
#define AMIGAFILTER

#include <sys/types.h>

class AmigaFilter
{
    public:
        AmigaFilter () : activeBleps(0)
        {
        }

        ~AmigaFilter () {
        }

        enum e_filterType
        {
            AMIGA500, AMIGA500_LED,
            AMIGA1200, AMIGA1200_LED,
            VANILLA
        };

        static void setFilterType(e_filterType filterType);
        static void setMixerFreq(int frequency);

        // This is needed for the calculateAge method
        void setNoteFreq(int frequency);

        // return output simulated as series of bleps
        int16_t outputSample();

        // Add a sample, with optional age
        void inputSample(int16_t sample, int age = 0);

        // Convert a 16 bit fraction (0xffff = 1.0) to Paula clock ticks
        inline int AmigaFilter::calculateAge(u_int16_t fraction)
        {
            return (fraction * paulaTicksPerNotePeriod) >> 16;
        }


        void advanceClock(const unsigned int cycles);

        // Called with no args advances the clock by 1/mixer_freq
        inline void advanceClock()
        {
            advanceClock(paulaTicksPerMixerPeriod);
        }
    private:
        /* 131072 to 0, 2048 entries */
#define BLEP_SCALE 17
#define BLEP_SIZE 2048
#define MAX_BLEPS 32

        /* the step function */
        // int32_t sineIntegral[BLEP_SIZE]; // = { precomputed table };

        /* the instantenous value of Paula output */
        int16_t globalOutputLevel;

        /* count of simultaneous bleps to keep track of */
        unsigned int activeBleps;

        /* the structure that holds data of bleps */
        typedef struct
        {
            int32_t level;
            int16_t age;
        } blepState_t;

        static e_filterType filterTable;
        static int paulaTicksPerMixerPeriod;
        int paulaTicksPerNotePeriod;

        /* place to keep our bleps in. MAX_BLEPS should be
           defined as a BLEP_SIZE / MINIMUM_EVENT_INTERVAL.
           For Paula, minimum event interval could be even 1, but it makes sense to
           limit it to some higher value such as 16. */
        blepState_t blepState[MAX_BLEPS];
};

#endif